#include <iostream>
#include <assert.h>
#include <queue>
#include <memory>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <sys/prctl.h>
using namespace std;


const int Thread_num=20;
template <class T>
class threadpool{
private:
    threadpool(const int num=Thread_num):threadnum(num)
    {
        assert(threadnum>0);
        isrunning=false;
        pthread_cond_init(&cond_,nullptr);
        pthread_mutex_init(&mutex_,nullptr);
    }
    threadpool(const threadpool<T> &)=delete;    //拷贝构造
    threadpool<T>& operator=(const threadpool<T>&)=delete;
public:
    ~threadpool(){
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }
    static threadpool<T>*getInstance(){
        static pthread_mutex_t mutex_static;
        if(instance==nullptr){
            //判断是否需要创建线程池
            pthread_mutex_lock(&mutex_static);
            if(instance==nullptr){
                instance=new threadpool<T>();
            }
            pthread_mutex_unlock(&mutex_static);
        }
        pthread_mutex_destroy(&mutex_static);
        return instance;
    }
    //类内函数默认第一个参数是this指针，而由于线程的执行函数只有一个参数，所以设置为静态函数，否则第一个参数被this占用
    static void* threadroutine(void* arg){
        pthread_detach(pthread_self()); //分离线程
        threadpool<T>* pool=static_cast<threadpool<T>* >(arg);
        //线程不断的获取任务，并执行
        while (true)
        {
            pool->lockQueue();
            //判断是否为空
            //为空则等待唤醒
            //不为空，取任务执行
            while (!pool->haveTask())
            {
                pool->waitForTask();
            }
            T t=pool->pop();
            pool->unlockQueue();
            t();
        }
        return nullptr;
    }
    void start(){
        assert(!isrunning);
        for(int i=0;i<threadnum;i++){
            pthread_t tid;
            pthread_create(&tid,nullptr,threadroutine,(void*)instance);
        }
    }

    void push(const T& t)
    {
        lockQueue();
        workqueue_.push(t);
        choiceThreadForHandler();
        unlockQueue();
    }
private:
    void lockQueue() { pthread_mutex_lock(&mutex_); }
    void unlockQueue() { pthread_mutex_unlock(&mutex_); }
    bool haveTask() { return !workqueue_.empty(); }
    void waitForTask() { pthread_cond_wait(&cond_, &mutex_); }
    void choiceThreadForHandler() { pthread_cond_signal(&cond_); }
    T pop()
    {
        T temp =workqueue_.front();
        workqueue_.pop();
        return temp;
    }
    queue<T> workqueue_;    //工作队列
    int threadnum;  //线程数量
    pthread_mutex_t mutex_; 
    pthread_cond_t cond_;
    bool isrunning; //判断线程池是否允许
    static threadpool<T>* instance;
};

template<class T>
threadpool<T>* threadpool<T>::instance=nullptr;
